/**
 * @File name: src/main.c
 * @Synopsis:
 * @Author: xing.dai@aliyun.com
 * @Version: 0.0.1
 * @Date: 2018-08-01 09:22
 */

#include "includes.h"
#include "device.h"
#include "test_char_dev.h"
#include "init.h"
//#include "board.h"

/**
 * @Synopsis  global variables.
 */
static OS_TCB		task_start_tcb;
static CPU_STK_SIZE	task_start_stk[APP_CFG_TASK_START_STK_SIZE];

static OS_TCB		task_shell_tcb;
static CPU_STK_SIZE	task_shell_stk[SHELL_TASK_STK_SIZE];

/**
 * @Synopsis  Function declaration.
 */
static void task_start_entry(void *arg);
static void create_shell_task(void);

/**
 * @Synopsis  main() entry
 *
 * @Returns  none
 */
int main(void)
{
    OS_ERR	err;

    hw_do_init(HW_INIT_LEVEL_0);
    hw_do_init(HW_INIT_LEVEL_1);
    hw_do_init(HW_INIT_LEVEL_2);
    hw_do_init(HW_INIT_LEVEL_3);

    sw_do_init(SW_INIT_LEVEL_0);
    //hw_do_init(HW_INIT_EARLY_LEVEL);
    //hw_do_init(HW_INIT_LEVEL); /* Init hardware in phase II. (Phase I in startup exec)*/
    //sw_do_init(SW_INIT_EARLY_LEVEL);
    OSInit(&err);	/* Initialize uCOS-III. */
    OSTaskCreate( (OS_TCB *)&task_start_tcb,
                  (CPU_CHAR *)"Task Start",
                  (OS_TASK_PTR)task_start_entry,
                  (void *)0,
                  (OS_PRIO)APP_CFG_TASK_START_PRIO,
                  (CPU_STK *)&task_start_stk[0],
                  (CPU_STK)(APP_CFG_TASK_START_STK_SIZE / 10),
                  (CPU_STK_SIZE)APP_CFG_TASK_START_STK_SIZE,
                  (OS_MSG_QTY)0,
                  (OS_TICK)0,
                  (void *)0,
                  (OS_OPT)(OS_OPT_TASK_STK_CHK | OS_OPT_TASK_STK_CLR),
                  (OS_ERR *)&err);
    OSStart(&err);	/* Start multitasking. */

//    while (DEF_TRUE) {
    /* Should never running here. */
//    }
    return 0;
}

static void create_shell_task(void)
{
    OS_ERR	err;
    OSTaskCreate( (OS_TCB *)&task_shell_tcb,
                  (CPU_CHAR *)"Task Shell",
                  (OS_TASK_PTR)task_shell_entry,
                  (void *)0,
                  (OS_PRIO)SHELL_TASK_PRIO,
                  (CPU_STK *)&task_shell_stk[0],
                  (CPU_STK)(SHELL_TASK_STK_SIZE / 10),
                  (CPU_STK_SIZE)SHELL_TASK_STK_SIZE,
                  (OS_MSG_QTY)0,
                  (OS_TICK)0,
                  (void *)0,
                  (OS_OPT)(OS_OPT_TASK_STK_CHK | OS_OPT_TASK_STK_CLR),
                  (OS_ERR *)&err);
}
/**
 * @Synopsis Start the first task.
 *
 * @Param arg
 *
 * @Returns none
 */
static void task_start_entry(void *arg)
{
    OS_ERR	err;
    (void)arg;

    CPU_Init();
    //Mem_Init();
    //Math_Init();
#ifndef ARCH_LINUX
    //hw_init_early();
#endif
    pool_init();
    device_tree_init();

#ifndef ARCH_LINUX
    //board_init();
#endif
    //sw_do_init(SW_INIT_LEVEL);

#if OS_CFG_STAT_TASK_EN > 0u
    OSStatTaskCPUUsageInit(&err);                               /* Compute CPU capacity with no task running            */
#endif

#ifdef CPU_CFG_INT_DIS_MEAS_EN
    CPU_IntDisMeasMaxCurReset();
#endif
    sw_do_init(SW_INIT_LEVEL_1);
    sw_do_init(SW_INIT_LEVEL_2);
    sw_do_init(SW_INIT_LEVEL_3);

    create_shell_task();

    show_basic_info();

    while (DEF_TRUE) {
        OSTimeDlyHMSM(0, 0, 1, 0,
                      OS_OPT_TIME_HMSM_STRICT,
                      &err);
    }


}

